Міністерство освіти і науки України
Національний університет “Львівська політехніка”
Кафедра ЕОМ
Лабораторна робота № 3a
з курсу ”Комп’ютері системи”
на тему: “Аналіз програмної моделі процесу роботи арифметичного конвеєра.”
Тема: Аналіз програмної моделі процесу роботи арифметичного конвеєра.
Мета роботи: Навчитись здійснювати аналіз програмних моделей
комп’ютерних систем, виконаних на мові System C.
Теоретична частина:
Удосконалення елементної бази вже не дає кардинального росту продуктивності обчислювальної системи. Більш перспективними у цьому плані розглядаються архітектурні рішення, серед яких одне із найбільш значимих – конвеєризація.
Рг вх -------→ ФБ -------------------→ Рг вих
Рис 1. Обробка інформації у одиночному блоці.
Для пояснення ідеї конвеєра розглянемо малюнок 1, де показаний окремий функціональний блок (ФБ). Вихідні дані завантажуються у у вхідний регістр Ргвх , обробляється у функціональному блоці, а результат обробки фіксується у вихідному регістрі Ргвих. Якщо максимальний час обробки у ФБ дорівнює Тmax , то нові дані можуть бути занесені у вхідний регістр Ргвх не раніше, ніж через Тmax.
Ргвх
(
ФБ1
(
Рг1
(
ФБ2
(
Рг2
(
ФБ3
(
Ргвих
Рис. 2. Обробка інформації у конвеєрі з регістрами.
Тепер розподілемо функції, що виконуються у функціональному блоці ФБ на малюнку 1 між трьома послідовними незалежними блоками: ФБ1 , ФБ2 і ФБ3, причому так, що б максимальний час обробки у кожному ФБi був однаковий і дорівнював Tmax/3. Між блоками розмістимо буферні регістри Ргі, що призначені для збереження результату обробки у ФБі, на випадок, якщо наступний за ним функціональний блок ще не готовий використовувати цей результат.
У розглянутій схемі дані на вхід конвеєра можуть подаватися х інтервалом Tmax/3 (тобто, втричі частіше), і хоча затримка від моменту поступлення першої одиниці даних у Ргвх до моменту появи результату її обробки на виході Ргвих як і раніше складає Tmax, наступні результати з’являються на виході Ргвих вже з інтервалом Tmax/3.
На практиці рідко вдається добитися того, щоб затримки у кожному ФБі були однаковими. Як наслідок, продуктивність конвеєра знижується, оскільки період поступлення вхідних даних визначається максимальним часом їх обробки у кожному функціональному блоці. Для усунення цього недоліку або, в решті решт, часткової його компенсації кожний буферний регістр Ргі потрібно замінити буферною пам’яттю БПі , здатною зберігати множину даних і організований за принципом FIFO – “перший зайшов – перший вийшов”.
БПвх
(
ФБ1
(
БП1
(
ФБ2
(
БП2
(
ФБ3
(
БПвих
Рис. 3. Обробка інформації у конвеєрі з буферною пам’ятю.
Обробивши елемент даних, ФБі заносить результат у БПі, витягає з БПі-1 новий елемент даних і починає черговий цикл обробки, причому ця послідовність здійснюється кожним функціональним блоком незалежно від інших блоків. Обробка у кожному блоці може продовжуватися до тих пір, доки не беде ліквідована попередня черга або доки не буде переповнена наступна черга. Якщо емність буферної пам’яті достатньо велика, різниця у часі обробки не відбивається на продуктивності, тим не менш бажано, щоб середня тривалість обробки у всіх ФБі була однаковою.
По способу синхронізації роботи ланок конвеєри можуть бути синхронні та асинхронні. Для традиційних комп’ютерів характерні синхронні конвеєри. Пов’язане це, наперед всього, із синхронним характером роботи процесорів. Ланки конвеєрів у процесорі звичайно розміщені близько одна від одної, завдяки чому тракти розповсюдження сигналів синхронізації виходять достатньо короткими і фактор “перекосу” сигналів стає не таким суттєвим.
Асинхронні конвеєри виявляються корисними, якщо зв’язок між ланками не така сильна, а довжина сигнальних трактів між різними ланками сильно відрізняється. Прикладом асинхронних конвеєрів можуть слугувати систолічні масиви.
Завдання:
Проаналізувати склад програмної моделі арифметичного конвеєра, (програма PIPE), яка виконана на мові System C.
Визначити інформаційні потоки у моделі арифметичного конвеєра.
Визначити зв’язки керування.
Накреслити блоки, з яких складається арифметичний конвеєр згідно поданої моделі.
Хід виконання роботи:
1) листинг програмної моделі арифметичного конвеєра на мові System C
File main.cpp
#include "systemc.h"
#include "stage1.h"
#include "stage2.h"
#include "stage3.h"
#include "display.h"
#include "numgen.h"
int sc_main(int ac, char *av[])
{
//Signals
sc_signal<double> in1;
sc_signal<double> in2;
sc_signal<double> sum;
sc_signal<double> diff;
sc_signal<double> prod;
sc_signal<double> quot;
sc_signal<double> powr;
//Clock
sc_signal<bool> clk;
numgen N("numgen"); //instance of `numgen' module
N(in1, in2, clk ); //Positional port binding
stage1 S1("stage1"); //instance of `stage1' module
//Named port binding
S1.in1(in1);
S1.in2(in2);
S1.sum(sum);
S1.diff(diff);
S1.clk(clk);
stage2 S2("stage2"); //instance of `stage2' module
S2(sum, diff, prod, quot, clk ); //Positional port binding
stage3 S3("stage3"); //instance of `stage3' module
S3( prod, quot, powr, clk); //Positional port binding
display D("display"); //instance of `display' module
D(powr, clk); //Positional port binding
sc_start(0, SC_NS); //Initialize simulation
for(int i = 0; i < 50; i++){
clk.write(1);
sc_start( 10, SC_NS );
clk.write(0);
sc_start( 10, SC_NS );
}
return 0;
}
File display.h
#ifndef DISPLAY_H
#define DISPLAY_H
struct display : sc_module {
sc_in<double> in; // input port 1
sc_in<bool> clk; // clock
void print_result(); // method to display input port values
//Constructor
SC_CTOR( display ) {
SC_METHOD( print_result ); // declare print_result as SC_METHOD and
dont_initialize();
sensitive << clk.pos(); // make it sensitive to positive clock edge
}
};
#endif
File display.cpp
#include "systemc.h"
#include "display.h"
#include <stdio.h>
//Definition of print_result method
void display::print_result()
{
printf("Result = %f\n", in.read());
} // end of print method
File numgen.h
#ifndef NUMGEN_H
#define NUMGEN_H
struct numgen : sc_module {
sc_out<double> out1; //output 1
sc_out<double> out2; //output 2
sc_in<bool> clk; //clock
// method to write values to the output ports
void generate();
//Constructor
SC_CTOR( numgen ) {
SC_METHOD( generate ); //Declare generate as SC_METHOD and
dont_initialize();
sensitive << clk.pos(); //make it sensitive to positive clock edge
}
};
#endif
File numgen.cpp
#include "systemc.h"
#include "numgen.h"
// definition of the `generate' method
void numgen::generate()
{
static double a = 134.56;
static double b = 98.24;
a -= 1.5;
b -= 2.8;
out1.write(a);
out2.write(b);
} // end of `generate' method
File stage1.h
#ifndef STAGE1_H
#define STAGE1_H
struct stage1 : sc_module {
sc_in<double> in1; //input 1
sc_in<double> in2; //input 2
sc_out<double> sum; //output 1
sc_out<double> diff; //output 2
sc_in<bool> clk; //clock
void addsub(); //method implementing functionality
//Counstructor
SC_CTOR( stage1 ) {
SC_METHOD( addsub ); //Declare addsub as SC_METHOD and
dont_initialize();
sensitive << clk.pos(); //make it sensitive to positive clock edge
}
};
File stage1.cpp
#include "systemc.h"
#include "stage1.h"
//Definition of addsub method
void stage1::addsub()
{
double a;
double b;
a = in1.read();
b = in2.read();
sum.write(a+b);
diff.write(a-b);
} // end of addsub method
File stage2.h
#ifndef STAGE2_H
#define STAGE2_H
struct stage2 : sc_module {
sc_in<double> sum; //input port 1
sc_in<double> diff; //input port 2
sc_out<double> prod; //output port 1
sc_out<double> quot; //output port 2
sc_in<bool> clk; //clock
void multdiv(); //method providing functionality
//Constructor
SC_CTOR( stage2 ) {
SC_METHOD( multdiv ); //Declare multdiv as SC_METHOD and
dont_initialize();
sensitive << clk.pos(); //make it sensitive to positive clock edge.
}
};
#endif
File stage2.cpp
#include "systemc.h"
#include "stage2.h"
//definition of multdiv method
void stage2::multdiv()
{
double a;
double b;
a = sum.read();
b = diff.read();
if( b == 0 )
b = 5.0;
prod.write(a*b);
quot.write(a/b);
} // end of multdiv
File stage3.h
#ifndef STAGE3_H
#define STAGE3_H
struct stage3: sc_module {
sc_in<double> prod; //input port 1
sc_in<double> quot; //input port 2
sc_out<double> powr; //output port 1
sc_in<bool> clk; //clock
void power(); //method implementing functionality
//Constructor
SC_CTOR( stage3 ){
SC_METHOD( power ); //declare power as SC_METHOD and
dont_initialize();
sensitive << clk.pos(); //make it sensitive to positive clock edge
}
};
#endif
File stage3.cpp
#include <math.h>
#include "systemc.h"
#include "stage3.h"
//Definition of power method
void stage3::power()
{
double a;
double b;
double c;
a = prod.read();
b = quot.read();
c = (a>0 && b>0)? pow(a, b) : 0.;
powr.write(c);
} // end of power method
2) перелік і призначення блоків арифметичного конвеєра
* модуль numgen:
static double a = 134.56;
static double b = 98.24;
a -= 1.5;
b -= 2.8;
записує на вихід в порти out1 - a i out2 - b.
* модуль stage1: Зчитує значення з портів in1 та in2. Результат додавання записує в sum а відніманя в diff.
* модуль stage2: Зчитує значення з портів sum та diff. Результат множення записує в prod а ділення в quot. Якщо значення зчитане з diff рівне 0, йому присвоюється значення 5.0.
* модуль stage3: Зчитує значення з портів quot та prod. Результат піднесення prod до степеня quot записує в powr. Якшо якийсь з параметрів не є більшим за 0 то на вихід записується 0.
* модуль display: Зчитує значення з порту in. Виводить його на екран.
3) структурну схему арифметичного конвеєра, яка відповідає програмній моделі