Merge branch 'stevehoover:main' into main

This commit is contained in:
Victor Timofei 2022-01-16 19:20:20 +02:00 committed by GitHub
commit ce288f2840
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 497 additions and 511 deletions

View File

@ -1,12 +1,5 @@
\m4_TLV_version 1d: tl-x.org \m4_TLV_version 1d: tl-x.org
\SV \SV
// =========================================
// Welcome! Try the tutorials via the menu.
// =========================================
// Default Makerchip TL-Verilog Code Template
// Macro providing required top-level module definition, random // Macro providing required top-level module definition, random
// stimulus support, and Verilator config. // stimulus support, and Verilator config.
m4_makerchip_module // (Expanded in Nav-TLV pane.) m4_makerchip_module // (Expanded in Nav-TLV pane.)
@ -14,13 +7,13 @@
// Visualization for calculator // Visualization for calculator
\TLV calc_viz() \TLV calc_viz()
// m4_ifelse_block(m4_sp_graph_dangerous, 1, , {{
\SV_plus \SV_plus
logic sticky_zero; logic sticky_zero;
assign sticky_zero = 0; assign sticky_zero = 0;
/view /view
\viz_alpha \viz_js
initEach() { box: {strokeWidth: 0},
init() {
let hexcalname = new fabric.Text("HEX Calc 3000", { let hexcalname = new fabric.Text("HEX Calc 3000", {
left: -150 + 150, left: -150 + 150,
top: -150 + 40, top: -150 + 40,
@ -157,7 +150,7 @@
fontSize: 22, fontSize: 22,
fontFamily: "Courier New", fontFamily: "Courier New",
}) })
let missing = new fabric.Text("", { this.missing = new fabric.Text("", {
top: 360, top: 360,
left: -160, left: -160,
fontSize: 16, fontSize: 16,
@ -182,24 +175,23 @@
height: 300, height: 300,
stroke: "black" stroke: "black"
}), }),
missing this.missing
], ],
{visible: false} {visible: false}
) )
return {missing, return {calbox, val1box, val1num, val2box, val2num,
objects: {calbox, val1box, val1num, val2box, val2num,
outbox, outnum, equalname, sumbox, minbox, prodbox, quotbox, sumicon, outbox, outnum, equalname, sumbox, minbox, prodbox, quotbox, sumicon,
prodicon, minicon: minicon, quoticon: quoticon, hexcalname, missing_sigs}}; prodicon, minicon: minicon, quoticon: quoticon, hexcalname, missing_sigs}
}, },
renderEach() { render() {
let missing_list = ""; let missing_list = "";
let sig_names = ["op", "val1", "val2", "out"]; let sig_names = ["op", "val1", "val2", "out"];
let sticky_zero = this.svSigRef(`sticky_zero`); let sticky_zero = this.svSigRef(`sticky_zero`);
getSig = (name) => { getSig = (name) => {
let sig = this.svSigRef(`L0_${name}_a0`); let sig = this.svSigRef(`L0_${name}_a0`);
if (sig == null) { if (sig == null) {
missing_list += `◾ ${name} \n`; missing_list += `◾ $${name} \n`;
sig = sticky_zero; sig = sticky_zero;
} }
return sig; return sig;
@ -208,18 +200,18 @@
result[sig_name] = getSig(sig_name) result[sig_name] = getSig(sig_name)
return result return result
}, {}) }, {})
this.getInitObject("val1num").set({text: sigs.val1.asInt(NaN).toString(16).padStart(8, " ")}) this.getObjects().val1num.set({text: sigs.val1.asInt(NaN).toString(16).padStart(8, " ")})
this.getInitObject("val2num").set({text: sigs.val2.asInt(NaN).toString(16).padStart(8, " ")}) this.getObjects().val2num.set({text: sigs.val2.asInt(NaN).toString(16).padStart(8, " ")})
this.getInitObject("outnum").set({text: sigs.out.asInt(NaN).toString(16).padStart(8, " ")}) this.getObjects().outnum.set({text: sigs.out.asInt(NaN).toString(16).padStart(8, " ")})
let op = sigs.op.asInt(NaN) let op = sigs.op.asInt(NaN)
this.getInitObject("sumbox").set({fill: op == 0 ? "#c0d0e0" : "#a0a0a0"}) this.getObjects().sumbox.set({fill: op == 0 ? "#c0d0e0" : "#a0a0a0"})
this.getInitObject("minbox").set({fill: op == 1 ? "#c0d0e0" : "#a0a0a0"}) this.getObjects().minbox.set({fill: op == 1 ? "#c0d0e0" : "#a0a0a0"})
this.getInitObject("prodbox").set({fill: op == 2 ? "#c0d0e0" : "#a0a0a0"}) this.getObjects().prodbox.set({fill: op == 2 ? "#c0d0e0" : "#a0a0a0"})
this.getInitObject("quotbox").set({fill: op == 3 ? "#c0d0e0" : "#a0a0a0"}) this.getObjects().quotbox.set({fill: op == 3 ? "#c0d0e0" : "#a0a0a0"})
if (missing_list) { if (missing_list) {
this.getInitObject("calbox").set({fill: "red"}) this.getObjects().calbox.set({fill: "red"})
this.getInitObject("missing_sigs").set({visible:true}) this.getObjects().missing_sigs.set({visible:true})
this.fromInit().missing.set({text: missing_list}) this.missing.set({text: missing_list})
} }
} }
\TLV \TLV

View File

@ -142,11 +142,9 @@ m4+definitions(['
$_port3_data[_width-1:0] = $rf1_rd_en2 ? /xreg[$rf1_rd_index2]$value : 'X; $_port3_data[_width-1:0] = $rf1_rd_en2 ? /xreg[$rf1_rd_index2]$value : 'X;
/xreg[m4_eval(_entries-1):0] /xreg[m4_eval(_entries-1):0]
\viz_alpha \viz_js
initEach: function() { box: {width: 120, height: 18, strokeWidth: 0},
return {} // {objects: {reg: reg}}; render() {
},
renderEach: function() {
siggen = (name) => this.svSigRef(`${name}`) == null ? this.svSigRef(`sticky_zero`) : this.svSigRef(`${name}`); siggen = (name) => this.svSigRef(`${name}`) == null ? this.svSigRef(`sticky_zero`) : this.svSigRef(`${name}`);
let rf_rd_en1 = siggen(`L0_rf1_rd_en1_a0`) let rf_rd_en1 = siggen(`L0_rf1_rd_en1_a0`)
@ -165,8 +163,8 @@ m4+definitions(['
let regIdent = reg.toString().padEnd(2, " ") let regIdent = reg.toString().padEnd(2, " ")
let newValStr = (regIdent + ": ").padEnd(14, " ") let newValStr = (regIdent + ": ").padEnd(14, " ")
let reg_str = new fabric.Text((regIdent + ": " + value.asInt(NaN).toString(M4_VIZ_BASE)).padEnd(14, " "), { let reg_str = new fabric.Text((regIdent + ": " + value.asInt(NaN).toString(M4_VIZ_BASE)).padEnd(14, " "), {
top: 18 * this.getIndex() - 40, top: 0,
left: 316, left: 0,
fontSize: 14, fontSize: 14,
fill: mod ? "blue" : "black", fill: mod ? "blue" : "black",
fontWeight: mod ? 800 : 400, fontWeight: mod ? 800 : 400,
@ -179,8 +177,9 @@ m4+definitions(['
this.global.canvas.renderAll() this.global.canvas.renderAll()
}, 1500) }, 1500)
} }
return {objects: [reg_str]} return [reg_str]
} },
where: {left: 316, top: -40}
// Data Memory // Data Memory
\TLV dmem(_entries, _width, $_reset, $_addr, $_port1_en, $_port1_data, $_port2_en, $_port2_data) \TLV dmem(_entries, _width, $_reset, $_addr, $_port1_en, $_port1_data, $_port2_en, $_port2_data)
@ -199,11 +198,9 @@ m4+definitions(['
$_port2_data[_width-1:0] = $dmem1_rd_en ? /dmem[$dmem1_addr]$value : 'X; $_port2_data[_width-1:0] = $dmem1_rd_en ? /dmem[$dmem1_addr]$value : 'X;
/dmem[m4_eval(_entries-1):0] /dmem[m4_eval(_entries-1):0]
\viz_alpha \viz_js
initEach: function() { box: {width: 120, height: 18, strokeWidth: 0},
return {} // {objects: {reg: reg}}; render() {
},
renderEach: function() {
siggen = (name) => this.svSigRef(`${name}`) == null ? this.svSigRef(`sticky_zero`) : this.svSigRef(`${name}`); siggen = (name) => this.svSigRef(`${name}`) == null ? this.svSigRef(`sticky_zero`) : this.svSigRef(`${name}`);
// //
let dmem_rd_en = siggen(`L0_dmem1_rd_en_a0`); let dmem_rd_en = siggen(`L0_dmem1_rd_en_a0`);
@ -218,8 +215,8 @@ m4+definitions(['
let regIdent = reg.toString().padEnd(2, " "); let regIdent = reg.toString().padEnd(2, " ");
let newValStr = (regIdent + ": ").padEnd(14, " "); let newValStr = (regIdent + ": ").padEnd(14, " ");
let dmem_str = new fabric.Text((regIdent + ": " + value.asInt(NaN).toString(M4_VIZ_BASE)).padEnd(14, " "), { let dmem_str = new fabric.Text((regIdent + ": " + value.asInt(NaN).toString(M4_VIZ_BASE)).padEnd(14, " "), {
top: 18 * this.getIndex() - 40, top: 0,
left: 480, left: 0,
fontSize: 14, fontSize: 14,
fill: mod ? "blue" : "black", fill: mod ? "blue" : "black",
fontWeight: mod ? 800 : 400, fontWeight: mod ? 800 : 400,
@ -232,8 +229,9 @@ m4+definitions(['
this.global.canvas.renderAll() this.global.canvas.renderAll()
}, 1500) }, 1500)
} }
return {objects: [dmem_str]} return [dmem_str]
} },
where: {left: 480, top: -40}
\TLV cpu_viz() \TLV cpu_viz()
// String representations of the instructions for debug. // String representations of the instructions for debug.
@ -245,10 +243,10 @@ m4+definitions(['
logic [40*8-1:0] instr_strs [0:M4_NUM_INSTRS]; logic [40*8-1:0] instr_strs [0:M4_NUM_INSTRS];
assign instr_strs = '{m4_asm_mem_expr "END "}; assign instr_strs = '{m4_asm_mem_expr "END "};
/cpuviz \viz_js
\viz_alpha
m4_define(['M4_IMEM_TOP'], ['m4_ifelse(m4_eval(M4_NUM_INSTRS > 16), 0, 0, m4_eval(0 - (M4_NUM_INSTRS - 16) * 18))']) m4_define(['M4_IMEM_TOP'], ['m4_ifelse(m4_eval(M4_NUM_INSTRS > 16), 0, 0, m4_eval(0 - (M4_NUM_INSTRS - 16) * 18))'])
initEach() { box: {strokeWidth: 0},
init() {
let imem_box = new fabric.Rect({ let imem_box = new fabric.Rect({
top: M4_IMEM_TOP - 50, top: M4_IMEM_TOP - 50,
left: -700, left: -700,
@ -328,7 +326,7 @@ m4+definitions(['
fontSize: 46, fontSize: 46,
fontWeight: 800 fontWeight: 800
}) })
let missing_col1 = new fabric.Text("", { this.missing_col1 = new fabric.Text("", {
top: 420, top: 420,
left: -480, left: -480,
fontSize: 16, fontSize: 16,
@ -336,7 +334,7 @@ m4+definitions(['
fontFamily: "monospace", fontFamily: "monospace",
fill: "purple" fill: "purple"
}) })
let missing_col2 = new fabric.Text("", { this.missing_col2 = new fabric.Text("", {
top: 420, top: 420,
left: -300, left: -300,
fontSize: 16, fontSize: 16,
@ -361,15 +359,14 @@ m4+definitions(['
height: 300, height: 300,
stroke: "black" stroke: "black"
}), }),
missing_col1, this.missing_col1,
missing_col2, this.missing_col2,
], ],
{visible: false} {visible: false}
) )
return {missing_col1, missing_col2, return {imem_box, decode_box, rf_box, dmem_box, imem_header, decode_header, rf_header, dmem_header, passed, missing_sigs}
objects: {imem_box, decode_box, rf_box, dmem_box, imem_header, decode_header, rf_header, dmem_header, passed, missing_sigs}};
}, },
renderEach() { render() {
// Strings (2 columns) of missing signals. // Strings (2 columns) of missing signals.
var missing_list = ["", ""] var missing_list = ["", ""]
var missing_cnt = 0 var missing_cnt = 0
@ -439,10 +436,10 @@ m4+definitions(['
let dmem_addr = siggen_rf_dmem("dmem1_addr") let dmem_addr = siggen_rf_dmem("dmem1_addr")
if (instr != sticky_zero) { if (instr != sticky_zero) {
this.getInitObjects().imem_box.setVisible(true) this.getObjects().imem_box.set({visible: true})
this.getInitObjects().imem_header.setVisible(true) this.getObjects().imem_header.set({visible: true})
this.getInitObjects().decode_box.setVisible(true) this.getObjects().decode_box.set({visible: true})
this.getInitObjects().decode_header.setVisible(true) this.getObjects().decode_header.set({visible: true})
} }
let pcPointer = new fabric.Text("👉", { let pcPointer = new fabric.Text("👉", {
top: M4_IMEM_TOP + 18 * (pc.asInt() / 4), top: M4_IMEM_TOP + 18 * (pc.asInt() / 4),
@ -499,12 +496,12 @@ m4+definitions(['
visible: dmem_wr_en.asBool() visible: dmem_wr_en.asBool()
}) })
if (rf_rd_en1 != sticky_zero) { if (rf_rd_en1 != sticky_zero) {
this.getInitObjects().rf_box.setVisible(true) this.getObjects().rf_box.set({visible: true})
this.getInitObjects().rf_header.setVisible(true) this.getObjects().rf_header.set({visible: true})
} }
if (dmem_rd_en != sticky_zero) { if (dmem_rd_en != sticky_zero) {
this.getInitObjects().dmem_box.setVisible(true) this.getObjects().dmem_box.set({visible: true})
this.getInitObjects().dmem_header.setVisible(true) this.getObjects().dmem_header.set({visible: true})
} }
@ -591,13 +588,13 @@ m4+definitions(['
}) })
if (dmem_rd_en.asBool()) { if (dmem_rd_en.asBool()) {
setTimeout(() => { setTimeout(() => {
load_viz.setVisible(true) load_viz.set({visible: true})
load_viz.animate({left: 146, top: 70}, { load_viz.animate({left: 146, top: 70}, {
onChange: this.global.canvas.renderAll.bind(this.global.canvas), onChange: this.global.canvas.renderAll.bind(this.global.canvas),
duration: 500 duration: 500
}) })
setTimeout(() => { setTimeout(() => {
load_viz.setVisible(false) load_viz.set({visible: false})
}, 500) }, 500)
}, 500) }, 500)
} }
@ -613,7 +610,7 @@ m4+definitions(['
}) })
if (dmem_wr_en.asBool()) { if (dmem_wr_en.asBool()) {
setTimeout(() => { setTimeout(() => {
store_viz.setVisible(true) store_viz.set({visible: true})
store_viz.animate({left: 515, top: 18 * dmem_addr.asInt() - 40}, { store_viz.animate({left: 515, top: 18 * dmem_addr.asInt() - 40}, {
onChange: this.global.canvas.renderAll.bind(this.global.canvas), onChange: this.global.canvas.renderAll.bind(this.global.canvas),
duration: 500 duration: 500
@ -641,8 +638,8 @@ m4+definitions(['
}) })
if (rd_valid.asBool()) { if (rd_valid.asBool()) {
setTimeout(() => { setTimeout(() => {
result_viz.setVisible(rf_wr_data != sticky_zero && rf_wr_en.asBool()) result_viz.set({visible: rf_wr_data != sticky_zero && rf_wr_en.asBool()})
result_shadow.setVisible(result != sticky_zero) result_shadow.set({visible: result != sticky_zero})
result_viz.animate({left: 317 + 8 * 4, top: 18 * rf_wr_index.asInt(0) - 40}, { result_viz.animate({left: 317 + 8 * 4, top: 18 * rf_wr_index.asInt(0) - 40}, {
onChange: this.global.canvas.renderAll.bind(this.global.canvas), onChange: this.global.canvas.renderAll.bind(this.global.canvas),
duration: 500 duration: 500
@ -653,16 +650,16 @@ m4+definitions(['
// Lab completion // Lab completion
// Passed? // Passed?
this.getInitObject("passed").setVisible(false) this.getObjects().passed.set({visible: false})
if (passed) { if (passed) {
if (passed.step(-1).asBool()) { if (passed.step(-1).asBool()) {
this.getInitObject("passed").set({visible: true, text:"Passed !!!", fill: "green"}) this.getObjects().passed.set({visible: true, text:"Passed !!!", fill: "green"})
} else { } else {
// Using an unstable API, so: // Using an unstable API, so:
try { try {
passed.goToSimEnd().step(-1) passed.goToSimEnd().step(-1)
if (passed.asBool()) { if (passed.asBool()) {
this.getInitObject("passed").set({text:"Sim Passes", visible: true, fill: "lightgray"}) this.getObjects().passed.set({text:"Sim Passes", visible: true, fill: "lightgray"})
} }
} catch(e) { } catch(e) {
} }
@ -671,57 +668,54 @@ m4+definitions(['
// Missing signals // Missing signals
if (missing_list[0]) { if (missing_list[0]) {
this.getInitObject("missing_sigs").setVisible(true) this.getObjects().missing_sigs.set({visible: true})
this.fromInit().missing_col1.set({text: missing_list[0]}) this.missing_col1.set({text: missing_list[0]})
this.fromInit().missing_col2.set({text: missing_list[1]}) this.missing_col2.set({text: missing_list[1]})
} }
return {objects: [pcPointer, pc_arrow, ...type_texts, rs1_arrow, rs2_arrow, rd_arrow, instrWithValues, fetch_instr_viz, src1_value_viz, src2_value_viz, result_shadow, result_viz, ld_arrow, st_arrow, load_viz, store_viz]}; return [pcPointer, pc_arrow, ...type_texts, rs1_arrow, rs2_arrow, rd_arrow, instrWithValues, fetch_instr_viz, src1_value_viz, src2_value_viz, result_shadow, result_viz, ld_arrow, st_arrow, load_viz, store_viz]
} }
/imem[m4_eval(M4_NUM_INSTRS-1):0] /imem[m4_eval(M4_NUM_INSTRS-1):0]
\viz_alpha \viz_js
initEach() { box: {width: 630, height: 18, strokeWidth: 0},
init() {
let binary = new fabric.Text("", { let binary = new fabric.Text("", {
top: M4_IMEM_TOP + 18 * this.getIndex(), top: 0,
left: -680, left: 0,
fontSize: 14, fontSize: 14,
fontFamily: "monospace", fontFamily: "monospace",
}) })
let disassembled = new fabric.Text("", { let disassembled = new fabric.Text("", {
top: M4_IMEM_TOP + 18 * this.getIndex(), top: 0,
left: -350, left: 330,
fontSize: 14, fontSize: 14,
fontFamily: "monospace" fontFamily: "monospace"
}) })
return {objects: {binary, disassembled}} return {binary, disassembled}
}, },
renderEach() { onTraceData() {
// Instruction memory is constant, so just create it once.
let reset = this.svSigRef(`L0_reset_a0`)
let pc = this.svSigRef(`L0_pc_a0`)
let rd_viz = pc && !reset.asBool() && (pc.asInt() >> 2) == this.getIndex()
if (!global.instr_mem_drawn) {
global.instr_mem_drawn = []
}
if (!global.instr_mem_drawn[this.getIndex()]) {
global.instr_mem_drawn[this.getIndex()] = true
let instr = this.svSigRef(`instrs(${this.getIndex()})`) let instr = this.svSigRef(`instrs(${this.getIndex()})`)
if (instr) { if (instr) {
let binary_str = instr.goToSimStart().asBinaryStr("") let binary_str = instr.goToSimStart().asBinaryStr("")
this.getInitObject("binary").set({text: binary_str}) this.getObjects().binary.set({text: binary_str})
} }
let disassembled = this.svSigRef(`instr_strs(${this.getIndex()})`) let disassembled = this.svSigRef(`instr_strs(${this.getIndex()})`)
if (disassembled) { if (disassembled) {
let disassembled_str = disassembled.goToSimStart().asString("") let disassembled_str = disassembled.goToSimStart().asString("")
disassembled_str = disassembled_str.slice(0, -5) disassembled_str = disassembled_str.slice(0, -5)
this.getInitObject("disassembled").set({text: disassembled_str}) this.getObjects().disassembled.set({text: disassembled_str})
}
}
this.getInitObject("disassembled").set({textBackgroundColor: rd_viz ? "#b0ffff" : "white"})
this.getInitObject("binary") .set({textBackgroundColor: rd_viz ? "#b0ffff" : "white"})
} }
},
render() {
// Instruction memory is constant, so just create it once.
let reset = this.svSigRef(`L0_reset_a0`)
let pc = this.svSigRef(`L0_pc_a0`)
let rd_viz = pc && !reset.asBool() && (pc.asInt() >> 2) == this.getIndex()
this.getObjects().disassembled.set({textBackgroundColor: rd_viz ? "#b0ffff" : "white"})
this.getObjects().binary .set({textBackgroundColor: rd_viz ? "#b0ffff" : "white"})
},
where: {left: -680, top: M4_IMEM_TOP}
\TLV tb() \TLV tb()
$passed_cond = (/xreg[30]$value == 32'b1) && $passed_cond = (/xreg[30]$value == 32'b1) &&