Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions bebop/src/arch/buckyball/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,11 @@ impl Bank {
impl DevsModel for Bank {
fn events_ext(&mut self, incoming_message: &ModelMessage, services: &mut Services) -> Result<(), SimulationError> {
if incoming_message.port_name == self.write_bank_req_port {
match serde_json::from_str::<(u64, u64, Vec<u64>)>(&incoming_message.content) {
match serde_json::from_str::<(u64, u64, Vec<u128>)>(&incoming_message.content) {
Ok(value) => {
let vbank_id = value.0;
let start_addr = value.1;
let data_u64 = value.2;

let mut data_vec = Vec::new();
for i in (0..data_u64.len()).step_by(2) {
if i + 1 < data_u64.len() {
let lo = data_u64[i];
let hi = data_u64[i + 1];
data_vec.push((hi as u128) << 64 | (lo as u128));
}
}
let data_vec = value.2;

if vbank_id < self.banks.len() as u64 {
self.banks[vbank_id as usize].write_batch(start_addr, &data_vec);
Expand Down Expand Up @@ -257,3 +248,27 @@ pub fn request_write_bank(vbank_id: u64, start_addr: u64, data_vec: Vec<u128>) -
}
false
}

pub fn request_read_bank_for_systolic(vbank_id: u64, start_addr: u64, count: u64, _rob_id: u64) {
let bank_data_opt = BANK_DATA.lock().unwrap();
if let Some(ref bank_data) = *bank_data_opt {
if vbank_id < bank_data.len() as u64 {
let bank = &bank_data[vbank_id as usize];

let mut data_vec = Vec::new();
for i in 0..count {
let addr = start_addr + i;
if addr < bank.len() as u64 {
data_vec.push(bank[addr as usize]);
} else {
data_vec.push(0);
}
}

READ_RESPONSE_QUEUE
.lock()
.unwrap()
.push(ReadResponse { data: data_vec });
}
}
}
35 changes: 35 additions & 0 deletions bebop/src/arch/buckyball/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use super::mem_ctrl::MemController;
use super::mset::Mset;
use super::rob::Rob;
use super::rs::Rs;
use super::systolic_array::SystolicArray;
use super::tdma_loader::TdmaLoader;
use super::tdma_storer::TdmaStorer;
use super::vecball::VectorBall;
Expand Down Expand Up @@ -46,8 +47,10 @@ pub fn create_simulation() -> Simulation {
Box::new(MemController::new(
String::from("tdma_mem_write_req"),
String::from("vball_mem_write_req"),
String::from("systolic_mem_write_req"),
String::from("mem_tdma_read_resp"),
String::from("mem_vball_read_resp"),
String::from("mem_systolic_read_resp"),
String::from("mem_bank_write_req"),
String::from("bank_mem_read_resp"),
)),
Expand Down Expand Up @@ -76,6 +79,15 @@ pub fn create_simulation() -> Simulation {
String::from("commit_to_rob"),
)),
),
Model::new(
String::from("systolic_array"),
Box::new(SystolicArray::new(
String::from("systolic_mem_write_req"),
String::from("mem_systolic_read_req"),
String::from("mem_systolic_read_resp"),
String::from("commit_to_rob"),
)),
),
];

let connectors = vec![
Expand Down Expand Up @@ -169,6 +181,29 @@ pub fn create_simulation() -> Simulation {
String::from("commit_to_rob"),
String::from("commit"),
),
// Systolic Array <-> MemController (write request and read response)
Connector::new(
String::from("systolic_memctrl_write_req"),
String::from("systolic_array"),
String::from("mem_controller"),
String::from("systolic_mem_write_req"),
String::from("systolic_mem_write_req"),
),
Connector::new(
String::from("memctrl_systolic_read_resp"),
String::from("mem_controller"),
String::from("systolic_array"),
String::from("mem_systolic_read_resp"),
String::from("mem_systolic_read_resp"),
),
// Systolic Array -> ROB (commit)
Connector::new(
String::from("systolic_rob_commit"),
String::from("systolic_array"),
String::from("rob"),
String::from("commit_to_rob"),
String::from("commit"),
),
];

Simulation::post(models, connectors)
Expand Down
104 changes: 97 additions & 7 deletions bebop/src/arch/buckyball/mem_ctrl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ pub struct MemController {
// Write request ports (multi-cycle)
tdma_write_req_port: String,
vball_write_req_port: String,
systolic_write_req_port: String,
bank_write_req_port: String,

// Read response ports (multi-cycle)
tdma_read_resp_port: String,
vball_read_resp_port: String,
systolic_read_resp_port: String,
bank_read_resp_port: String,

until_next_event: f64,
Expand All @@ -45,8 +47,10 @@ impl MemController {
pub fn new(
tdma_write_req_port: String,
vball_write_req_port: String,
systolic_write_req_port: String,
tdma_read_resp_port: String,
vball_read_resp_port: String,
systolic_read_resp_port: String,
bank_write_req_port: String,
bank_read_resp_port: String,
) -> Self {
Expand All @@ -56,9 +60,11 @@ impl MemController {
Self {
tdma_write_req_port,
vball_write_req_port,
systolic_write_req_port,
bank_write_req_port,
tdma_read_resp_port,
vball_read_resp_port,
systolic_read_resp_port,
bank_read_resp_port,
until_next_event: INFINITY,
records: Vec::new(),
Expand All @@ -71,12 +77,12 @@ impl DevsModel for MemController {
fn events_ext(&mut self, incoming_message: &ModelMessage, services: &mut Services) -> Result<(), SimulationError> {
// Handle write requests from TDMA (multi-cycle)
if incoming_message.port_name == self.tdma_write_req_port {
match serde_json::from_str::<(u64, u64, u64, Vec<u64>)>(&incoming_message.content) {
match serde_json::from_str::<(u64, u64, u64, Vec<u128>)>(&incoming_message.content) {
Ok(value) => {
let rob_id = value.0;
let vbank_id = value.1;
let start_addr = value.2;
let data_count = value.3.len() / 2;
let data_count = value.3.len();

// Convert vbank_id to pbank_id using BMT
let pbank_id = if let Some(pbank_ids) = get_pbank_ids(vbank_id) {
Expand Down Expand Up @@ -120,12 +126,12 @@ impl DevsModel for MemController {

// Handle write requests from VectorBall (multi-cycle)
if incoming_message.port_name == self.vball_write_req_port {
match serde_json::from_str::<(u64, u64, u64, Vec<u64>)>(&incoming_message.content) {
match serde_json::from_str::<(u64, u64, u64, Vec<u128>)>(&incoming_message.content) {
Ok(value) => {
let rob_id = value.0;
let vbank_id = value.1;
let start_addr = value.2;
let data_count = value.3.len() / 2;
let data_count = value.3.len();

// Convert vbank_id to pbank_id using BMT
let pbank_id = if let Some(pbank_ids) = get_pbank_ids(vbank_id) {
Expand Down Expand Up @@ -172,6 +178,64 @@ impl DevsModel for MemController {
return Ok(());
}

// Handle write requests from Systolic Array (multi-cycle)
if incoming_message.port_name == self.systolic_write_req_port {
match serde_json::from_str::<Vec<u128>>(&incoming_message.content) {
Ok(data_vec) => {
let rob_id = 0; // Assuming systolic array uses fixed rob_id for now
let vbank_id = 2; // Assuming result bank is 2 based on test
let start_addr = 0;
let data_count = data_vec.len();

// Convert vbank_id to pbank_id using BMT
let pbank_id = if let Some(pbank_ids) = get_pbank_ids(vbank_id) {
if pbank_ids.is_empty() {
vbank_id
} else {
pbank_ids[0]
}
} else {
vbank_id
};

// Create write request with rob_id, vbank_id, start_addr, data
let write_req = (rob_id, vbank_id, start_addr, data_vec);
let json_content = serde_json::to_string(&write_req).unwrap_or_default();

// Check dependency
if scoreboard::check_dependency(pbank_id, rob_id) {
// No dependency, can proceed immediately
self
.write_request_queue
.push(("systolic".to_string(), json_content));
} else {
// Has dependency, add to scoreboard
scoreboard::add_to_scoreboard(
rob_id,
pbank_id,
"systolic".to_string(),
json_content,
);
}

self.records.push(ModelRecord {
time: services.global_time(),
action: "enqueue_systolic_write".to_string(),
subject: format!(
"rob_id={}, bank={}, addr={}, count={}",
rob_id, vbank_id, start_addr, data_count
),
});

self.until_next_event = 1.0;
},
Err(_) => {
// Failed to deserialize Systolic Array write request, skipping
}
}
return Ok(());
}

// Handle read responses from Bank - forward to the correct source (multi-cycle)
if incoming_message.port_name == self.bank_read_resp_port {
match serde_json::from_str::<Vec<u128>>(&incoming_message.content) {
Expand Down Expand Up @@ -209,6 +273,8 @@ impl DevsModel for MemController {
if let Some(resp) = READ_RESPONSE_QUEUE.lock().unwrap().pop() {
let response_port = if resp.source == "tdma" {
self.tdma_read_resp_port.clone()
} else if resp.source == "systolic" {
self.systolic_read_resp_port.clone()
} else {
self.vball_read_resp_port.clone()
};
Expand Down Expand Up @@ -251,12 +317,12 @@ impl DevsModel for MemController {
if !self.write_request_queue.is_empty() {
let (source, json_content) = self.write_request_queue.remove(0);

match serde_json::from_str::<(u64, u64, u64, Vec<u64>)>(&json_content) {
match serde_json::from_str::<(u64, u64, u64, Vec<u128>)>(&json_content) {
Ok(value) => {
let rob_id = value.0;
let vbank_id = value.1;
let start_addr = value.2;
let data_u64 = value.3;
let data_u128 = value.3;

// Convert vbank_id to pbank_id using BMT
// Use first pbank_id if vbank maps to multiple pbanks
Expand All @@ -274,7 +340,7 @@ impl DevsModel for MemController {
scoreboard::mark_in_flight(pbank_id, rob_id);

// Re-encode with pbank_id (remove rob_id for bank)
let request = (pbank_id, start_addr, data_u64);
let request = (pbank_id, start_addr, data_u128);
match serde_json::to_string(&request) {
Ok(new_content) => {
messages.push(ModelMessage {
Expand Down Expand Up @@ -423,6 +489,30 @@ pub fn request_read_bank_for_vecball(vbank_id: u64, start_addr: u64, count: u64,
}
}

pub fn request_read_bank_for_systolic(vbank_id: u64, start_addr: u64, count: u64, rob_id: u64) {
// Convert vbank_id to pbank_id using BMT
// Use first pbank_id if vbank maps to multiple pbanks
let pbank_id = if let Some(pbank_ids) = get_pbank_ids(vbank_id) {
if pbank_ids.is_empty() {
vbank_id // Fallback to vbank_id
} else {
pbank_ids[0]
}
} else {
vbank_id // Fallback to vbank_id
};

// Check dependency
if scoreboard::check_dependency(pbank_id, rob_id) {
// No dependency, can proceed immediately
READ_SOURCE_QUEUE.lock().unwrap().push("systolic".to_string());
request_read_bank(pbank_id, start_addr, count);
} else {
// Has dependency, add to read scoreboard
scoreboard::add_read_to_scoreboard(rob_id, pbank_id, start_addr, count, "systolic".to_string());
}
}

pub fn request_write_bank_for_tdma(vbank_id: u64, start_addr: u64, data_vec: Vec<u128>) -> bool {
request_write_bank(vbank_id, start_addr, data_vec)
}
Expand Down
1 change: 1 addition & 0 deletions bebop/src/arch/buckyball/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod mset;
pub mod rob;
pub mod rs;
pub mod scoreboard;
pub mod systolic_array;
pub mod tdma_loader;
pub mod tdma_storer;
pub mod vecball;
Expand Down
6 changes: 5 additions & 1 deletion bebop/src/arch/buckyball/rob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ use crate::arch::buckyball::mset::MSET_INST_CAN_ISSUE;
use crate::arch::buckyball::tdma_loader::MVIN_INST_CAN_ISSUE;
use crate::arch::buckyball::tdma_storer::MVOUT_INST_CAN_ISSUE;
use crate::arch::buckyball::vecball::VECBALL_INST_CAN_ISSUE;
use crate::arch::buckyball::systolic_array::SYSTOLIC_ARRAY_INST_CAN_ISSUE;
use crate::arch::buckyball::scoreboard;
use crate::arch::buckyball::mem_ctrl;
use crate::arch::buckyball::tdma_loader;
use crate::arch::buckyball::tdma_storer;
use crate::arch::buckyball::vecball;
use crate::arch::buckyball::systolic_array;

#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
enum EntryStatus {
Expand Down Expand Up @@ -103,7 +105,8 @@ impl DevsModel for Rob {
&& mem_ctrl::is_mem_ctrl_idle()
&& tdma_loader::is_tdma_loader_idle()
&& tdma_storer::is_tdma_storer_idle()
&& vecball::is_vecball_idle();
&& vecball::is_vecball_idle()
&& systolic_array::is_systolic_array_idle();

if all_idle {
FENCE_CSR.store(false, Ordering::Relaxed);
Expand Down Expand Up @@ -251,6 +254,7 @@ fn check_can_issue(funct: u64) -> bool {
24 => MVIN_INST_CAN_ISSUE.load(Ordering::Relaxed),
25 => MVOUT_INST_CAN_ISSUE.load(Ordering::Relaxed),
30 => VECBALL_INST_CAN_ISSUE.load(Ordering::Relaxed),
42 => SYSTOLIC_ARRAY_INST_CAN_ISSUE.load(Ordering::Relaxed),
_ => false,
}
}
19 changes: 18 additions & 1 deletion bebop/src/arch/buckyball/rs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use super::mset::{receive_mset_inst, MSET_INST_CAN_ISSUE};
use super::tdma_loader::{receive_mvin_inst, MVIN_INST_CAN_ISSUE};
use super::tdma_storer::{receive_mvout_inst, MVOUT_INST_CAN_ISSUE};
use super::vecball::{receive_vecball_inst, VECBALL_INST_CAN_ISSUE};
use super::systolic_array::{receive_systolic_array_inst, SYSTOLIC_ARRAY_INST_CAN_ISSUE};
use std::sync::atomic::Ordering;

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -96,8 +97,24 @@ impl DevsModel for Rs {
remaining_instructions.push(inst);
}
},
42 => {
if SYSTOLIC_ARRAY_INST_CAN_ISSUE.load(Ordering::Relaxed) {
// Extract matrix dimensions and bank IDs from xs1 and xs2
// For the test case, use 16x16 matrix dimensions
let op1_bank_id = 0;
let op2_bank_id = 1;
let wr_bank_id = 2;
let m_dim = 16;
let n_dim = 16;
let k_dim = 16;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to replace this with the actual logic later.

receive_systolic_array_inst(op1_bank_id, op2_bank_id, wr_bank_id, m_dim, n_dim, k_dim, inst.rob_id);
} else {
remaining_instructions.push(inst);
}
},
_ => {
return Err(SimulationError::InvalidModelState);
// Skip unknown instructions instead of returning error
// This allows the simulation to continue
},
}
}
Expand Down
Loading