Skip to content

Commit c35a3b3

Browse files
committed
sim interface annotation working
1 parent 56aa580 commit c35a3b3

File tree

8 files changed

+318
-134
lines changed

8 files changed

+318
-134
lines changed

chipflow_lib/_signatures.py

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#undef NDEBUG
2+
3+
#include <cxxrtl/cxxrtl.h>
4+
#include <cxxrtl/cxxrtl_server.h>
5+
#include "sim_soc.h"
6+
{% for include in includes %}
7+
#include "{{include}}"
8+
{% endfor %}
9+
10+
#include <fstream>
11+
#include <filesystem>
12+
13+
using namespace cxxrtl::time_literals;
14+
using namespace cxxrtl_design;
15+
16+
int main(int argc, char **argv) {
17+
p_sim__top top;
18+
19+
{% for initialiser in initialisers %}
20+
{{initialiser}};
21+
{% endfor %}
22+
23+
cxxrtl::agent agent(cxxrtl::spool("spool.bin"), top);
24+
if (getenv("DEBUG")) // can also be done when a condition is violated, etc
25+
std::cerr << "Waiting for debugger on " << agent.start_debugging() << std::endl;
26+
27+
open_event_log(BUILD_DIR "/sim/events.json");
28+
open_input_commands(PROJECT_ROOT "/design/tests/input.json");
29+
30+
unsigned timestamp = 0;
31+
auto tick = [&]() {
32+
{% for interface in interfaces %}
33+
{{interface}}.step(timestamp);
34+
{% endfor %}
35+
36+
// FIXME: Currently we tick all clocks together, this need fixing..
37+
{% for clock in clocks %}
38+
top.{{clock}}.set(false);
39+
{% endfor %}
40+
agent.step();
41+
agent.advance(1_us);
42+
++timestamp;
43+
44+
{% for clock in clocks %}
45+
top.{{clock}}.set(true);
46+
{% endfor %}
47+
agent.step();
48+
agent.advance(1_us);
49+
++timestamp;
50+
51+
// if (timestamp == 10)
52+
// agent.breakpoint(CXXRTL_LOCATION);
53+
};
54+
55+
flash.load_data(BUILD_DIR "/software/software.bin", 0x00100000U);
56+
agent.step();
57+
agent.advance(1_us);
58+
59+
{% for reset in resets %}
60+
top.{{reset}}.set(false);
61+
{% endfor %}
62+
63+
tick();
64+
65+
{% for reset in resets %}
66+
top.{{reset}}.set(true);
67+
{% endfor %}
68+
69+
for (int i = 0; i < 3000000; i++)
70+
tick();
71+
72+
close_event_log();
73+
return 0;
74+
}

chipflow_lib/common/sim/models.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ struct spi_model {
127127

128128
struct i2c_model {
129129
std::string name;
130-
i2c_model(const std::string &name, const value<1> &sda_oe, value<1> &sda_i, const value<1> &scl_oe, value<1> &scl_i) : name(name), sda_oe(sda_oe), sda_i(sda_i), scl_oe(scl_oe), scl_i(scl_i) {};
130+
i2c_model(const std::string &name, const value<1> &sda_o, const value<1> &sda_oe, value<1> &sda_i, const value<1> &scl_o, const value<1> &scl_oe, value<1> &scl_i) : name(name), sda_oe(sda_oe), sda_i(sda_i), scl_oe(scl_oe), scl_i(scl_i) {};
131131

132132
void step(unsigned timestamp);
133133
private:

chipflow_lib/platforms/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
)
1515
from ._packages import PACKAGE_DEFINITIONS
1616
from ._sky130 import Sky130DriveMode
17+
from ._signatures import JTAGSignature, SPISignature, I2CSignature, UARTSignature, GPIOSignature, QSPIFlashSignature
1718

1819
__all__ = ['IO_ANNOTATION_SCHEMA', 'IOSignature',
1920
'IOModel', 'IOModelOptions', 'IOTripPoint',
2021
'OutputIOSignature', 'InputIOSignature', 'BidirIOSignature',
2122
'SiliconPlatformPort', 'SiliconPlatform',
2223
'SimPlatform',
24+
'JTAGSignature', 'SPISignature', 'I2CSignature', 'UARTSignature', 'GPIOSignature',
2325
'Sky130DriveMode',
2426
'PACKAGE_DEFINITIONS']
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# SPDX-License-Identifier: BSD-2-Clause
2+
3+
from typing_extensions import Unpack, TypedDict
4+
5+
from amaranth.lib import wiring
6+
from amaranth.lib.wiring import Out
7+
8+
from ._utils import InputIOSignature, OutputIOSignature, BidirIOSignature, IOModelOptions, _chipflow_schema_uri, amaranth_annotate
9+
10+
SIM_ANNOTATION_SCHEMA = str(_chipflow_schema_uri("sim-interface", 0))
11+
12+
class SimInterface(TypedDict):
13+
name: str
14+
parameters: dict
15+
16+
17+
def sim_annotate(klass):
18+
original_init_subclass = klass.__init_subclass__
19+
20+
def new_init_subclass(cls, /, **kwargs):
21+
original_init = cls.__init__
22+
def new_init(self,*args, **kwargs):
23+
original_init(self, *args, **kwargs)
24+
self._model = {
25+
"name": cls.__name__,
26+
"parameters": self._get_sim_parameters(),
27+
}
28+
29+
if original_init_subclass:
30+
original_init_subclass(**kwargs)
31+
cls.__init__ = new_init
32+
33+
dec = amaranth_annotate(SimInterface, SIM_ANNOTATION_SCHEMA)
34+
klass = dec(klass)
35+
klass.__init_subclass__ = classmethod(new_init_subclass)
36+
klass._get_sim_parameters = lambda self: {}
37+
return klass
38+
39+
40+
@sim_annotate
41+
class SimulatableSignature(wiring.Signature):
42+
...
43+
44+
class JTAGSignature(SimulatableSignature):
45+
def __init__(self, **kwargs: Unpack[IOModelOptions]):
46+
super().__init__({
47+
"trst": Out(InputIOSignature(1)),
48+
"tck": Out(InputIOSignature(1)),
49+
"tms": Out(InputIOSignature(1)),
50+
"tdi": Out(InputIOSignature(1)),
51+
"tdo": Out(OutputIOSignature(1)),
52+
})
53+
54+
55+
class SPISignature(SimulatableSignature):
56+
def __init__(self, **kwargs: Unpack[IOModelOptions]):
57+
super().__init__({
58+
"sck": Out(OutputIOSignature(1)),
59+
"copi": Out(OutputIOSignature(1)),
60+
"cipo": Out(InputIOSignature(1)),
61+
"csn": Out(OutputIOSignature(1)),
62+
})
63+
64+
class QSPIFlashSignature(SimulatableSignature):
65+
def __init__(self, **kwargs: Unpack[IOModelOptions]):
66+
super().__init__({
67+
"clk": Out(OutputIOSignature(1)),
68+
"csn": Out(OutputIOSignature(1)),
69+
"d": Out(BidirIOSignature(4, individual_oe=True)),
70+
})
71+
72+
class UARTSignature(SimulatableSignature):
73+
def __init__(self, **kwargs: Unpack[IOModelOptions]):
74+
super().__init__({
75+
"tx": Out(OutputIOSignature(1)),
76+
"rx": Out(InputIOSignature(1)),
77+
})
78+
79+
class I2CSignature(SimulatableSignature):
80+
def __init__(self, **kwargs: Unpack[IOModelOptions]):
81+
super().__init__({
82+
"scl": Out(BidirIOSignature(1)),
83+
"sda": Out(BidirIOSignature(1))
84+
})
85+
86+
class GPIOSignature(SimulatableSignature):
87+
def __init__(self, pin_count=1, **kwargs: Unpack[IOModelOptions]):
88+
if pin_count > 32:
89+
raise ValueError(f"Pin pin_count must be lesser than or equal to 32, not {pin_count}")
90+
self._pin_count = pin_count
91+
kwargs['individual_oe'] = True
92+
super().__init__({
93+
"gpio": Out(BidirIOSignature(pin_count, **kwargs))
94+
})
95+
def _get_sim_parameters(self):
96+
return {'pin_count': self._pin_count}
97+
98+
def __repr__(self) -> str:
99+
return f"GPIOSignature(pin_count={self._pin_count}, {dict(self.members.items())})"

chipflow_lib/platforms/_utils.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,13 @@ class IOModel(IOModelOptions):
130130
width: int
131131
direction: Annotated[io.Direction, PlainSerializer(lambda x: x.value)]
132132

133-
def amaranth_annotate(model: Type[TypedDict], schema_id: str):
133+
def amaranth_annotate(modeltype: Type[TypedDict], schema_id: str):
134+
PydanticModel = TypeAdapter(modeltype)
135+
134136
def annotation_schema():
135137
class Model(pydantic.BaseModel):
136-
data_td: model
138+
data_td: modeltype
137139

138-
PydanticModel = TypeAdapter(model)
139140
schema = PydanticModel.json_schema()
140141
schema['$schema'] = "https://json-schema.org/draft/2020-12/schema"
141142
schema['$id'] = schema_id
@@ -145,21 +146,19 @@ class Annotation(meta.Annotation):
145146
"Generated annotation class"
146147
schema = annotation_schema()
147148

148-
def __init__(self, model:IOModel):
149+
def __init__(self, model: modeltype):
149150
self._model = model
150151

151152
@property
152153
def origin(self): # type: ignore
153154
return self._model
154155

155156
def as_json(self): # type: ignore
156-
return TypeAdapter(IOModel).dump_python(self._model)
157+
return PydanticModel.dump_python(self._model)
157158

158159
def annotations(self, *args): # type: ignore
159160
annotations = wiring.Signature.annotations(self, *args) # type: ignore
160-
print(f"annotating {self} with {self._model}")
161161
annotation = Annotation(self._model)
162-
print(f"returning {annotations + (annotation,)}")
163162
return annotations + (annotation,) # type: ignore
164163

165164
def decorator(klass):
@@ -386,17 +385,17 @@ def _group_consecutive_items(ordering: PinList, lst: PinList) -> OrderedDict[int
386385
last = lst[0]
387386
current_group = [last]
388387

389-
logger.debug(f"_group_consecutive_items starting with {current_group}")
388+
#logger.debug(f"_group_consecutive_items starting with {current_group}")
390389

391390
for item in lst[1:]:
392391
idx = ordering.index(last)
393392
next = ordering[idx + 1] if idx < len(ordering) - 1 else None
394-
logger.debug(f"inspecting {item}, index {idx}, next {next}")
393+
#logger.debug(f"inspecting {item}, index {idx}, next {next}")
395394
if item == next:
396395
current_group.append(item)
397-
logger.debug("found consecutive, adding to current group")
396+
#logger.debug("found consecutive, adding to current group")
398397
else:
399-
logger.debug("found nonconsecutive, creating new group")
398+
#logger.debug("found nonconsecutive, creating new group")
400399
grouped.append(current_group)
401400
current_group = [item]
402401
last = item

0 commit comments

Comments
 (0)