Skip to content

Commit a5c00a3

Browse files
authored
Merge pull request #3 from QuickLogic-Corp/memory_libmap
memory libmap support
2 parents b411f22 + 955074d commit a5c00a3

File tree

77 files changed

+11758
-18439
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+11758
-18439
lines changed

ql-qlf-plugin/Makefile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ SOURCES = synth_quicklogic.cc \
2525
ql-dsp-simd.cc \
2626
ql-dsp-macc.cc \
2727
ql-bram-split.cc \
28+
ql-bram-merge.cc \
2829
ql-dsp-io-regs.cc \
2930
ql-bram-asymmetric.cc
3031

@@ -57,12 +58,15 @@ VERILOG_MODULES = $(COMMON)/cells_sim.v \
5758
$(QLF_K6N10F_DIR)/dsp_sim.v \
5859
$(QLF_K6N10F_DIR)/primitives_sim.v \
5960
$(QLF_K6N10F_DIR)/brams_sim.v \
61+
$(QLF_K6N10F_DIR)/bram_types_sim.v \
6062
$(QLF_K6N10F_DIR)/sram1024x18.v \
6163
$(QLF_K6N10F_DIR)/TDP18K_FIFO.v \
6264
$(QLF_K6N10F_DIR)/ufifo_ctl.v \
6365
$(QLF_K6N10F_DIR)/ffs_map.v \
6466
$(QLF_K6N10F_DIR)/dsp_map.v \
6567
$(QLF_K6N10F_DIR)/dsp_final_map.v \
68+
$(QLF_K6N10F_DIR)/libmap_brams_map.v \
69+
$(QLF_K6N10F_DIR)/libmap_brams.txt \
6670
$(PP3_DIR)/abc9_map.v \
6771
$(PP3_DIR)/abc9_model.v \
6872
$(PP3_DIR)/abc9_unmap.v \
@@ -88,8 +92,8 @@ $(PMGEN_OUT_DIR):
8892

8993
DEPS := $(PMGEN_OUT_DIR)/ql-dsp-pm.h \
9094
$(PMGEN_OUT_DIR)/ql-dsp-macc.h \
91-
$(PMGEN_OUT_DIR)/ql-bram-asymmetric-wider-write.h \
92-
$(PMGEN_OUT_DIR)/ql-bram-asymmetric-wider-read.h
95+
$(PMGEN_OUT_DIR)/ql-bram-asymmetric-wider-write.h \
96+
$(PMGEN_OUT_DIR)/ql-bram-asymmetric-wider-read.h
9397

9498
$(DEPS): $(PMGEN_PY) | $(PMGEN_OUT_DIR)
9599

@@ -107,6 +111,9 @@ $(PMGEN_OUT_DIR)/ql-bram-asymmetric-wider-write.h: ql-bram-asymmetric-wider-writ
107111
$(PMGEN_OUT_DIR)/ql-bram-asymmetric-wider-read.h: ql-bram-asymmetric-wider-read.pmg
108112
python3 $(PMGEN_PY) -o $@ -p ql_bram_asymmetric_wider_read ql-bram-asymmetric-wider-read.pmg
109113

114+
$(QLF_K6N10F_DIR)/bram_types_sim.v: $(QLF_K6N10F_DIR)/generate_bram_types_sim.py
115+
python3 $^ $@
116+
110117
install_modules: $(VERILOG_MODULES)
111118
$(foreach f,$^,install -D $(f) $(YOSYS_DATA_DIR)/quicklogic/$(f);)
112119

ql-qlf-plugin/ql-bram-merge.cc

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/*
2+
* yosys -- Yosys Open SYnthesis Suite
3+
*
4+
* Copyright (C) 2023 N. Engelhardt <[email protected]>
5+
*
6+
* Permission to use, copy, modify, and/or distribute this software for any
7+
* purpose with or without fee is hereby granted, provided that the above
8+
* copyright notice and this permission notice appear in all copies.
9+
*
10+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17+
*
18+
*/
19+
20+
#include "kernel/log.h"
21+
#include "kernel/register.h"
22+
#include "kernel/rtlil.h"
23+
#include "kernel/sigtools.h"
24+
25+
USING_YOSYS_NAMESPACE
26+
PRIVATE_NAMESPACE_BEGIN
27+
28+
// ============================================================================
29+
30+
31+
32+
struct QlBramMergeWorker {
33+
34+
const RTLIL::IdString split_cell_type = ID($__QLF_TDP36K);
35+
const RTLIL::IdString merged_cell_type = ID($__QLF_TDP36K_MERGED);
36+
37+
// can be used to record parameter values that have to match on both sides
38+
typedef dict<RTLIL::IdString, RTLIL::Const> MergeableGroupKeyType;
39+
40+
RTLIL::Module *module;
41+
dict<MergeableGroupKeyType, pool<RTLIL::Cell*>> mergeable_groups;
42+
43+
QlBramMergeWorker(RTLIL::Module* module) : module(module)
44+
{
45+
for (RTLIL::Cell* cell : module->selected_cells())
46+
{
47+
if(cell->type != split_cell_type) continue;
48+
if(!cell->hasParam(ID(OPTION_SPLIT))) continue;
49+
if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1, 32)) continue;
50+
mergeable_groups[get_key(cell)].insert(cell);
51+
}
52+
}
53+
54+
static MergeableGroupKeyType get_key(RTLIL::Cell* cell)
55+
{
56+
MergeableGroupKeyType key;
57+
// For now, there are no restrictions on which cells can be merged
58+
(void) cell;
59+
return key;
60+
}
61+
62+
const dict<RTLIL::IdString, RTLIL::IdString>& param_map(bool second)
63+
{
64+
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
65+
{ ID(INIT), ID(INIT1) },
66+
{ ID(PORT_A_WIDTH), ID(PORT_A1_WIDTH) },
67+
{ ID(PORT_B_WIDTH), ID(PORT_B1_WIDTH) },
68+
{ ID(PORT_A_WR_BE_WIDTH), ID(PORT_A1_WR_BE_WIDTH) },
69+
{ ID(PORT_B_WR_BE_WIDTH), ID(PORT_B1_WR_BE_WIDTH) }
70+
};
71+
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
72+
{ ID(INIT), ID(INIT2) },
73+
{ ID(PORT_A_WIDTH), ID(PORT_A2_WIDTH) },
74+
{ ID(PORT_B_WIDTH), ID(PORT_B2_WIDTH) },
75+
{ ID(PORT_A_WR_BE_WIDTH), ID(PORT_A2_WR_BE_WIDTH) },
76+
{ ID(PORT_B_WR_BE_WIDTH), ID(PORT_B2_WR_BE_WIDTH) }
77+
};
78+
79+
if(second)
80+
return bram2_map;
81+
else
82+
return bram1_map;
83+
}
84+
85+
const dict<RTLIL::IdString, RTLIL::IdString>& port_map(bool second)
86+
{
87+
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
88+
{ ID(PORT_A_CLK), ID(PORT_A1_CLK) },
89+
{ ID(PORT_B_CLK), ID(PORT_B1_CLK) },
90+
{ ID(PORT_A_CLK_EN), ID(PORT_A1_CLK_EN) },
91+
{ ID(PORT_B_CLK_EN), ID(PORT_B1_CLK_EN) },
92+
{ ID(PORT_A_ADDR), ID(PORT_A1_ADDR) },
93+
{ ID(PORT_B_ADDR), ID(PORT_B1_ADDR) },
94+
{ ID(PORT_A_WR_DATA), ID(PORT_A1_WR_DATA) },
95+
{ ID(PORT_B_WR_DATA), ID(PORT_B1_WR_DATA) },
96+
{ ID(PORT_A_WR_EN), ID(PORT_A1_WR_EN) },
97+
{ ID(PORT_B_WR_EN), ID(PORT_B1_WR_EN) },
98+
{ ID(PORT_A_WR_BE), ID(PORT_A1_WR_BE) },
99+
{ ID(PORT_B_WR_BE), ID(PORT_B1_WR_BE) },
100+
{ ID(PORT_A_RD_DATA), ID(PORT_A1_RD_DATA) },
101+
{ ID(PORT_B_RD_DATA), ID(PORT_B1_RD_DATA) }
102+
};
103+
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
104+
{ ID(PORT_A_CLK), ID(PORT_A2_CLK) },
105+
{ ID(PORT_B_CLK), ID(PORT_B2_CLK) },
106+
{ ID(PORT_A_CLK_EN), ID(PORT_A2_CLK_EN) },
107+
{ ID(PORT_B_CLK_EN), ID(PORT_B2_CLK_EN) },
108+
{ ID(PORT_A_ADDR), ID(PORT_A2_ADDR) },
109+
{ ID(PORT_B_ADDR), ID(PORT_B2_ADDR) },
110+
{ ID(PORT_A_WR_DATA), ID(PORT_A2_WR_DATA) },
111+
{ ID(PORT_B_WR_DATA), ID(PORT_B2_WR_DATA) },
112+
{ ID(PORT_A_WR_EN), ID(PORT_A2_WR_EN) },
113+
{ ID(PORT_B_WR_EN), ID(PORT_B2_WR_EN) },
114+
{ ID(PORT_A_WR_BE), ID(PORT_A2_WR_BE) },
115+
{ ID(PORT_B_WR_BE), ID(PORT_B2_WR_BE) },
116+
{ ID(PORT_A_RD_DATA), ID(PORT_A2_RD_DATA) },
117+
{ ID(PORT_B_RD_DATA), ID(PORT_B2_RD_DATA) }
118+
};
119+
120+
if(second)
121+
return bram2_map;
122+
else
123+
return bram1_map;
124+
}
125+
126+
void merge_brams(RTLIL::Cell* bram1, RTLIL::Cell* bram2)
127+
{
128+
129+
// Create the new cell
130+
RTLIL::Cell* merged = module->addCell(NEW_ID, merged_cell_type);
131+
log_debug("Merging split BRAM cells %s and %s -> %s\n", log_id(bram1->name), log_id(bram2->name), log_id(merged->name));
132+
133+
for (auto &it : param_map(false))
134+
{
135+
if(bram1->hasParam(it.first))
136+
merged->setParam(it.second, bram1->getParam(it.first));
137+
}
138+
for (auto &it : param_map(true))
139+
{
140+
if(bram2->hasParam(it.first))
141+
merged->setParam(it.second, bram2->getParam(it.first));
142+
}
143+
144+
for (auto &it : port_map(false))
145+
{
146+
if (bram1->hasPort(it.first))
147+
merged->setPort(it.second, bram1->getPort(it.first));
148+
else
149+
log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram1->name));
150+
}
151+
for (auto &it : port_map(true))
152+
{
153+
if (bram2->hasPort(it.first))
154+
merged->setPort(it.second, bram2->getPort(it.first));
155+
else
156+
log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram2->name));
157+
}
158+
merged->attributes = bram1->attributes;
159+
for (auto attr: bram2->attributes)
160+
if (!merged->has_attribute(attr.first))
161+
merged->attributes.insert(attr);
162+
163+
// Remove the old cells
164+
module->remove(bram1);
165+
module->remove(bram2);
166+
167+
}
168+
169+
void merge_bram_groups()
170+
{
171+
for (auto &it : mergeable_groups)
172+
{
173+
while (it.second.size() > 1)
174+
{
175+
merge_brams(it.second.pop(), it.second.pop());
176+
}
177+
}
178+
}
179+
180+
};
181+
182+
struct QlBramMergePass : public Pass {
183+
184+
QlBramMergePass() : Pass("ql_bram_merge", "Infers QuickLogic k6n10f BRAM pairs that can operate independently") {}
185+
186+
void help() override
187+
{
188+
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
189+
log("\n");
190+
log(" ql_bram_merge [selection]\n");
191+
log("\n");
192+
log(" This pass identifies k6n10f 18K BRAM cells and packs pairs of them together\n");
193+
log(" into a TDP36K cell operating in split mode\n");
194+
log("\n");
195+
}
196+
197+
198+
199+
void execute(std::vector<std::string> args, RTLIL::Design *design) override
200+
{
201+
log_header(design, "Executing QL_BRAM_MERGE pass.\n");
202+
203+
size_t argidx = 1;
204+
extra_args(args, argidx, design);
205+
206+
for (RTLIL::Module* module : design->selected_modules())
207+
{
208+
QlBramMergeWorker worker(module);
209+
worker.merge_bram_groups();
210+
}
211+
}
212+
213+
214+
} QlBramMergePass;
215+
216+
PRIVATE_NAMESPACE_END

0 commit comments

Comments
 (0)