Fletchgen
The Fletcher Design Generator
mmio.cc
1 // Copyright 2018-2019 Delft University of Technology
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "fletchgen/mmio.h"
16 
17 #include <fletcher/fletcher.h>
18 #include <fletcher/common.h>
19 #include <cerata/api.h>
20 #include <cerata/vhdl/vhdl.h>
21 #include <memory>
22 #include <string>
23 #include <fstream>
24 #include <algorithm>
25 
26 #include "fletchgen/axi4_lite.h"
27 #include "fletchgen/basic_types.h"
28 
29 namespace fletchgen {
30 
31 using cerata::vector;
32 using cerata::component;
33 
34 static std::string ToString(MmioBehavior behavior) {
35  switch (behavior) {
36  case MmioBehavior::STATUS: return "status";
37  case MmioBehavior::STROBE: return "strobe";
38  default: return "control";
39  }
40 }
41 
42 static Port::Dir ToDir(MmioBehavior behavior) {
43  switch (behavior) {
44  case MmioBehavior::STATUS: return Port::Dir::IN;
45  case MmioBehavior::STROBE: return Port::Dir::OUT;
46  default: return Port::Dir::OUT;
47  }
48 }
49 
50 MmioPort::MmioPort(const std::string &name, Port::Dir dir, const MmioReg &reg,
51  const std::shared_ptr<ClockDomain> &domain) :
52  Port(name, reg.width == 1 ? cerata::bit() : vector(reg.width), dir, domain), reg(reg) {}
53 
54 std::shared_ptr<cerata::Object> MmioPort::Copy() const {
55  return std::make_shared<MmioPort>(name(), dir_, reg, domain_);
56 }
57 
58 std::shared_ptr<MmioPort> mmio_port(Port::Dir dir, const MmioReg &reg, const std::shared_ptr<ClockDomain> &domain) {
59  return std::make_shared<MmioPort>(reg.name, dir, reg, domain);
60 }
61 
62 std::shared_ptr<Component> mmio(const std::vector<fletcher::RecordBatchDescription> &batches,
63  const std::vector<MmioReg> &regs,
64  Axi4LiteSpec axi_spec) {
65  // Clock/reset port.
66  // TODO(johanpel): Everything is on the kernel clock domain now until vhdmmio gets CDC support.
67  auto kcd = port("kcd", cr(), Port::Dir::IN, kernel_cd());
68  // Create the component.
69  auto comp = component("mmio", {kcd});
70  // Generate all ports and add to the component.
71  for (const auto &reg : regs) {
72  auto dir = ToDir(reg.behavior);
73  auto port = mmio_port(dir, reg, kernel_cd());
74  // Change the name to vhdmmio convention.
75  port->SetName("f_" + reg.name + (std::string(dir == Port::Dir::IN ? "_write" : "") + "_data"));
76  comp->Add(port);
77  }
78  // Add the bus interface.
79  auto bus = axi4_lite(Port::Dir::IN, bus_cd(), axi_spec);
80  comp->Add(bus);
81 
82  // This will be a primitive component generated by vhdmmio.
83  comp->SetMeta(cerata::vhdl::meta::PRIMITIVE, "true");
84  comp->SetMeta(cerata::vhdl::meta::LIBRARY, "work");
85  comp->SetMeta(cerata::vhdl::meta::PACKAGE, "mmio_pkg");
86 
87  return comp;
88 }
89 
90 // Calculate how much address space is used by this register, given a width and an alignment.
91 static size_t AddrSpaceUsed(uint32_t width, uint32_t alignment) {
92  return (alignment / 8) * (width / alignment + (width % alignment != 0));
93 }
94 
95 static size_t Offset(uint32_t address, uint32_t alignment) {
96  return 8 * (address % (alignment / 8));
97 }
98 
99 std::string GenerateVhdmmioYaml(const std::vector<std::vector<MmioReg> *> &regs,
100  Axi4LiteSpec axi_spec,
101  std::optional<size_t *> next_addr) {
102  std::stringstream ss;
103  // The next free byte address.
104  size_t next_free_addr = axi_spec.offset;
105  // Header:
106  ss << "metadata:\n"
107  " name: mmio\n"
108  " doc: Fletchgen generated MMIO configuration.\n"
109  " \n"
110  "entity:\n"
111  " bus-flatten: yes\n"
112  " bus-prefix: mmio_\n"
113  " clock-name: kcd_clk\n"
114  " reset-name: kcd_reset\n"
115  "\n"
116  "features:\n"
117  " bus-width: " << std::to_string(axi_spec.data_width) << "\n";
118  ss << " optimize: yes\n"
119  "\n"
120  "interface:\n"
121  " flatten: yes\n"
122  "\n"
123  "fields: \n";
124 
125  // Iterate over the registers and generate the appropriate YAML lines.
126  for (const auto &sub : regs) {
127  for (auto &r : *sub) {
128  // Determine the address.
129  if (r.addr) {
130  // There is a fixed address.
131  ss << " - address: " << axi_spec.offset + *r.addr << "\n";
132  // Just take this address plus its space as the next address. This limits how the vector of MmioRegs can be
133  // supplied (fixed addr. must be at the start of the vector and ordered), but we don't currently use this in
134  // any other way.
135  next_free_addr = axi_spec.offset + *r.addr + AddrSpaceUsed(r.width, 32);
136  } else {
137  // There is not a fixed address.
138  ss << " - address: " << next_free_addr << "\n";
139  r.addr = next_free_addr;
140  next_free_addr += AddrSpaceUsed(r.width, 32);
141  }
142  // Set doc, name and other stuff.
143  ss << " name: " << r.name << "\n";
144  if (!r.desc.empty()) {
145  ss << " doc: " << r.desc << "\n";
146  }
147  auto offset = Offset(r.addr.value(), axi_spec.data_width);
148  if (r.width > 1) {
149  ss << " bitrange: " << offset + r.index + r.width - 1 << ".." << offset + r.index << "\n";
150  } else {
151  ss << " bitrange: " << offset + r.index << "\n";
152  }
153  ss << " behavior: " << ToString(r.behavior) << "\n";
154  ss << "\n";
155  }
156  }
157 
158  if (next_addr) {
159  **next_addr = next_free_addr;
160  }
161 
162  return ss.str();
163 }
164 
166  switch (fun) {
169  case MmioFunction::BATCH: return true;
170  default:return false;
171  }
172 }
173 
174 } // namespace fletchgen
Contains all classes and functions related to Fletchgen.
Definition: array.cc:29
std::shared_ptr< MmioPort > mmio_port(Port::Dir dir, const MmioReg &reg, const std::shared_ptr< ClockDomain > &domain)
Create an mmio port.
Definition: mmio.cc:58
std::shared_ptr< ClockDomain > kernel_cd()
Fletcher accelerator clock domain.
Definition: basic_types.cc:62
std::shared_ptr< Type > cr()
Fletcher clock/reset;.
Definition: basic_types.cc:73
MmioBehavior
Register access behavior enumeration.
Definition: mmio.h:61
@ STATUS
Register contents is controlled by hardware kernel.
@ STROBE
Register contents is asserted for one cycle by host software.
std::shared_ptr< Type > bus(const BusSpecParams &spec)
Fletcher bus type with access mode conveyed through spec of params.
Definition: bus.cc:166
std::shared_ptr< Axi4LitePort > axi4_lite(Port::Dir dir, const std::shared_ptr< ClockDomain > &domain, Axi4LiteSpec spec)
Make a new AXI4-lite port, returning a shared pointer to it.
Definition: axi4_lite.cc:67
MmioFunction
Register intended use enumeration.
Definition: mmio.h:52
@ KERNEL
Registers for the kernel.
@ BATCH
Registers for RecordBatch metadata.
@ DEFAULT
Default registers.
bool ExposeToKernel(MmioFunction fun)
Return true if an mmio register's function must cause it to be exposed to the user kernel.
Definition: mmio.cc:165
std::shared_ptr< ClockDomain > bus_cd()
Fletcher bus clock domain.
Definition: basic_types.cc:67
std::string GenerateVhdmmioYaml(const std::vector< std::vector< MmioReg > * > &regs, Axi4LiteSpec axi_spec, std::optional< size_t * > next_addr)
Returns a YAML string for the vhdmmio tool based on a set of registers.
Definition: mmio.cc:99
std::shared_ptr< Component > mmio(const std::vector< fletcher::RecordBatchDescription > &batches, const std::vector< MmioReg > &regs, Axi4LiteSpec axi_spec)
Generate the MMIO component for the nucleus.
Definition: mmio.cc:62
AXI4-lite bus specification.
Definition: axi4_lite.h:29
size_t offset
The offset for all registers.
Definition: axi4_lite.h:41
size_t data_width
The data width.
Definition: axi4_lite.h:37
std::shared_ptr< Object > Copy() const override
Make a copy of this MmioPort.
Definition: mmio.cc:54
MmioReg reg
The Mmio register this port will represent.
Definition: mmio.h:112
MmioPort(const std::string &name, Port::Dir dir, const MmioReg &reg, const std::shared_ptr< ClockDomain > &domain=cerata::default_domain())
MmioPort constructor.
Definition: mmio.cc:50
Structure to represent an MMIO register.
Definition: mmio.h:68
std::string name
Register mame.
Definition: mmio.h:90